﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace AppBrowser
{
    public partial class frmDownloadUpdates : Form
    {
        public frmDownloadUpdates()
        {
            InitializeComponent();
        }

        public List<UpdateLibrary.UpdateSection> DownloadQueue = new List<UpdateLibrary.UpdateSection>();
        private bool BusyDownload = false;
        private WebClient webClient = new WebClient();
        private int CurrentIndex = 0;
        private string _TempDownloadPath = "R:\\";
        public string TempDownloadPath
        {
            get { return _TempDownloadPath; }
            set { _TempDownloadPath = value; }
        }

        public AppData data;


        private string _UPDATEURL;
        public string UpdateUrl
        {
            get { return _UPDATEURL; }
            set { _UPDATEURL = value; }
        }

        public int QueueCount
        {
            get { return this.DownloadQueue.Count; }
        }

        public void AddFileToQueue(string url, string filename)
        {
            UpdateLibrary.UpdateSection u = new UpdateLibrary.UpdateSection(filename);
            u.FileUrl = url;
            u.FileName = filename;
            
            DownloadQueue.Add(u);
        }

        public void AddFileToQueue(UpdateLibrary.UpdateSection updateSection)
        {
            DownloadQueue.Add(updateSection);
        }


        private void CheckForUpdates()
        {
            /*
            // check for new version
            UpdateLibrary.UpdateClient upd = new UpdateLibrary.UpdateClient();
            upd.DownloadPath = _TempDownloadPath;
            upd.VersionUrl = _UPDATEURL;

            Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

            bool msgshown = false;
            if (upd.NewVersionAvailable("AppBrowser", v.ToString()))
            {
                UpdateLibrary.UpdateSection vInfo = upd.GetVersionInfo("AppBrowser");
                msgshown = true;
                if (MessageBox.Show(string.Format("A new version ({0}) is available\r\nDescription: {1}\r\n\r\nWould you like to download it\r\n"
                      , vInfo.Version, vInfo.Description), "New Version Available", MessageBoxButtons.OKCancel) == DialogResult.OK)
                {
                    // ok download new version
                    DownloadAppUpdate(vInfo);
                    return;
                }
            }

            // now check for database updates
            UpdateLibrary.UpdateSection vDb = upd.GetVersionInfo("AppBrowserDB");

            DateTime dbDate = ConvertFromUniversalDate(data.GetDatabaseDate());
            DateTime relDate = ConvertFromUniversalDate(vDb.ReleaseDate);

            if (relDate > dbDate)
            {
                // new database, dl automatically
                AddFileToQueue(vDb);
            }


            if (DownloadQueue.Count > 0)
            {
                lblStatus.Text = "Found " + DownloadQueue.Count + " Updates";
                btnCancel.Enabled = true;
            }
            else
            {
                lblStatus.Text = "Up to date";

                if (!msgshown)
                {
                    MessageBox.Show("You are up to date", "Current Version Up to Date");
                    this.Close();
                }
                

            }
            */
        }


        private void frmDownloadUpdates_Load(object sender, EventArgs e)
        {
            lblStatus.Text = "Checking for updates...";
            CheckForUpdates();            
        }

        private void EnableDownloadBtn(bool enable)
        {
            btnCancel.Enabled = enable;
        }

        /// <summary>
        /// Download Application Update
        /// </summary>
        private void DownloadAppUpdate(UpdateLibrary.UpdateSection update)
        {
            if (!webClient.IsBusy)
            {
                lblStatus.Text = "Downloading Application Update ("+update.Version+")";

                btnCancel.Visible = false;
                this.Height = this.Height - 20;
                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(AppDownloadCompleted);
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
                webClient.DownloadFileAsync(new Uri(update.FileUrl), _TempDownloadPath + "\\" + update.FileName);
            }
        }

        private void AppDownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            // notify completion
            ProcessAppDownload();
        }

        private void ProcessAppDownload()
        {
            lblStatus.Text = "Processing Application Update..";
        }



        public void StartBatchDownload()
        {
            CurrentIndex = 0;
            DownloadNextFile();
        }

        /// <summary>
        /// Download a file from the queue
        /// </summary>
        /// <param name="QueueIndex"></param>
        private void DownloadNextFile()
        {
            bool workercompleted = false;
            if (!webClient.IsBusy)
            {
                if (CurrentIndex < DownloadQueue.Count)
                {
                    UpdateLibrary.UpdateSection dlItem = DownloadQueue[CurrentIndex];

                    lblStatus.Text = string.Format("({0}/{1} Downloading...{2}",
                                    CurrentIndex, DownloadQueue.Count, dlItem.FileName);

                    webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);

                    CurrentIndex++;
                    workercompleted = false;
                    webClient.DownloadFileAsync(new Uri(dlItem.FileUrl), _TempDownloadPath + "\\" + dlItem.FileName);
                }
                else
                {
                    workercompleted = true;

                }
            }

            if (workercompleted)
            {
                // last item completed                  
                lblStatus.Text = string.Format("{0}/{1} Files Completed..",CurrentIndex,DownloadQueue.Count);
                btnCancel.Text = "Close";
                ProcessDownloads();
            }


        }


        /// <summary>
        /// Database update, just a simple copy to AppData directory
        /// </summary>
        /// <param name="updateSection"></param>
        private void _ProcessDatabaseUpdate(UpdateLibrary.UpdateSection updateSection)
        {
            string filepath = _TempDownloadPath+"\\"+ updateSection.FileName;

            lblStatus.Text = "Updating Database Definitions File...";
            // backup current database
            try
            {
                string bakFilePath= AppData.AppDataPath + "\\AppDatabase_" + DateTime.Now.ToString("yyyyMMdd") + ".xml";
                File.Copy(AppData.AppDataPath+"\\AppDatabase.xml", bakFilePath,true);

                // now copy downloaded file
                File.Copy(filepath, AppData.AppDataPath + "\\AppDatabase.xml",true);

                lblStatus.Text = "Database updated to " + updateSection.ReleaseDate;
            }
            catch(Exception ex) 
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        ///  Process files once downloaded
        /// </summary>
        private void ProcessDownloads()
        {
            foreach (UpdateLibrary.UpdateSection us in DownloadQueue)
            {
                if (File.Exists(_TempDownloadPath + "\\" +us.FileName) && us.UpdateType == "fulldatabase")
                {
                    _ProcessDatabaseUpdate(us);
                }
            }
        }

        private void CancelDownloads()
        {
            webClient.CancelAsync();
            BusyDownload = false;
        }
        private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            // Console.Write('+');
            progressBar1.Value = e.ProgressPercentage;
        }

        private void Completed(object sender, AsyncCompletedEventArgs e)
        {                      
            // notify completion
            DownloadNextFile();
        }

        private DateTime ConvertFromUniversalDate(string UniversalDate)
        {
            string[] pieces = UniversalDate.Split('-');
            DateTime dt = new DateTime(Convert.ToInt32(pieces[0]), Convert.ToInt32(pieces[1]), Convert.ToInt32(pieces[2]));
            return dt;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (btnCancel.Text == "Update Now")
            {
                // Start download
                btnCancel.Text = "Cancel";
                StartBatchDownload();
            }
            else if(btnCancel.Text == "Cancel")
            {
                // Cancel download
                btnCancel.Text = "Update Now";
                CancelDownloads();
            }
        }

    }
}
